package csc.fresher_group2.dao;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.FileAttribute;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;

import com.sun.org.apache.bcel.internal.generic.IINC;
import com.sun.org.apache.xpath.internal.functions.Function;

import csc.fresher_group2.model.FileInfo;
import csc.fresher_group2.model.UserLog;

/**
 * Class FileDAO manage file
 * 
 * @author Phuc
 */
public class IFileDAOImpl implements IFileDAO {
	/**
	 *
	 * @param path
	 * @return File get from path
	 */
	@Override
	public File getFileName(String path) {
		File file = new File(path);
		return file;
	}

	/**
	 * 
	 * @param path
	 * @return array file from path
	 */
	@Override
	public FileInfo[] getFiles(String path) {
		// TODO Auto-generated method stub
		File file = new File(path);
		if (file.isFile()) {

			FileInfo fInfo = new FileInfo(file.getName(), file.getPath(),
					file.isDirectory(), Utils.convertFileSize(file.length()),
					Utils.convertDateTimeFromLongNumber(file.lastModified()));
			return new FileInfo[] { fInfo };
		} else {
			int nFile = file.listFiles().length;
			FileInfo fInfo[] = new FileInfo[nFile];
			for (int i = 0; i < nFile; i++) {
				long sizeOfFile = 0;
				if (file.listFiles()[i].isFile())
					sizeOfFile = file.listFiles()[i].length();
				else
					sizeOfFile = FileUtils.sizeOfDirectory(file.listFiles()[i]);
				fInfo[i] = new FileInfo(
						file.listFiles()[i].getName(),
						file.listFiles()[i].getPath(),
						file.listFiles()[i].isDirectory(),
						Utils.convertFileSize(sizeOfFile),
						Utils.convertDateTimeFromLongNumber(file.lastModified()));
			}
			return fInfo;
		}
	}

	/**
	 * 
	 * @param path
	 * @return array file from path
	 */
	@Override
	public FileInfo[] getFilesExceptTrash(String path) {
		// TODO Auto-generated method stub
		File file = new File(path);
		if (file.isFile()) {

			FileInfo fInfo = new FileInfo(file.getName(), file.getPath(),
					file.isDirectory(), Utils.convertFileSize(file.length()),
					Utils.convertDateTimeFromLongNumber(file.lastModified()));
			return new FileInfo[] { fInfo };
		} else {
			int nFile = file.listFiles().length;
			List<FileInfo> fInfo = new ArrayList<FileInfo>();
			for (int i = 0; i < nFile; i++) {
				long sizeOfFile = 0;

				if (file.listFiles()[i].isFile()) {

					sizeOfFile = file.listFiles()[i].length();
					fInfo.add(new FileInfo(file.listFiles()[i].getName(), file
							.listFiles()[i].getPath(), file.listFiles()[i]
							.isDirectory(), Utils.convertFileSize(sizeOfFile),
							Utils.convertDateTimeFromLongNumber(file
									.lastModified())));
				} else {
					if (!file.listFiles()[i].getName().equals("trash")) {
						sizeOfFile = FileUtils
								.sizeOfDirectory(file.listFiles()[i]);
						fInfo.add(new FileInfo(file.listFiles()[i].getName(),
								file.listFiles()[i].getPath(),
								file.listFiles()[i].isDirectory(), Utils
										.convertFileSize(sizeOfFile), Utils
										.convertDateTimeFromLongNumber(file
												.lastModified())));
					}

				}
			}
			return fInfo.toArray(new FileInfo[0]);
		}
	}

	/**
	 * 
	 * @param src
	 * @param des
	 * @return true if upload file success, false if fail
	 * @throws IOException
	 */
	@Override
	public boolean uploadFile(String src, String des) throws IOException {
		// TODO Auto-generated method stub
		return copyFile(src, des);
	}

	/**
	 * 
	 * @param src
	 * @param des
	 * @return true if copy success, false if not success
	 * @throws IOException
	 */
	@Override
	public boolean copyFile(String src, String des) throws IOException {

		File source = new File(src);

		File dest = new File(des);
		if (source.isFile() == true) {
			dest = new File(dest.getPath() + "\\" + source.getName());
			FileUtils.copyFile(source, dest);
		} else {
			FileUtils.copyDirectory(source, dest);
		}

		ILog iLog = new ILogImpl();
		Date date = new Date();
		UserLog log = new UserLog("admin", "Copy file " + src + " to " + des,
				date);
		iLog.log(log);
		return true;

	}

	/**
	 * 
	 * @param src
	 * @return true if delete a file success, false if fail
	 * @throws IOException
	 */
	@Override
	public boolean deleteFile(String src, String dest) throws IOException {
		// File dest = new File(src);
		ILog iLog = new ILogImpl();
		Date date = new Date();
		UserLog log = new UserLog("admin", "Delete file from " + src + " to "
				+ dest, date);
		iLog.log(log);
		return this.moveFile(src, dest);
	}

	/**
	 * 
	 * @param src
	 * @return true if download file success, false if fail
	 */
	@Override
	public boolean downloadFile(String src) {
		// TODO Auto-generated method stub
		return false;
	}

	/**
	 * 
	 * @param path
	 * @return new File if create success, return null if not
	 */
	@Override
	public FileInfo newFolder(String path, boolean bNew)
			throws SecurityException {
		// TODO Auto-generated method stub
		File file = new File(path);

		if (file.exists() && bNew == true) {
			return newFolder(path + "1", bNew);
		}

		file.mkdir();
		ILog iLog = new ILogImpl();
		Date date = new Date();

		UserLog log = new UserLog("admin", "Create folder " + file.getName()
				+ " in " + path, date);
		iLog.log(log);
		FileInfo fInfo = new FileInfo(file.getName(), file.getPath(),
				file.isDirectory(), Utils.convertFileSize(file.length()),
				Utils.convertDateTimeFromLongNumber(file.lastModified()));
		return fInfo;
	}

	/**
	 * 
	 * @param path
	 * @return share's link of file
	 */
	@Override
	public String shareAFile(String path) {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 *
	 * @param src
	 *            : path of the folder need remove
	 * @param des
	 *            : path of the folder destination
	 * @return true if move success, false if move not success
	 * @throws IOException
	 */
	@Override
	public boolean moveFile(String src, String des) throws IOException {
		File source = new File(src);
		File dest = new File(des);

		ILog iLog = new ILogImpl();
		Date date = new Date();

		if (source.isFile() == true) {
			FileUtils.moveFileToDirectory(source, dest, true);
			UserLog log = new UserLog("admin", "Move file " + source.getName()
					+ " to " + dest.getPath(), date);
			iLog.log(log);
		} else {
			FileUtils.copyDirectoryToDirectory(source, dest);
			FileUtils.deleteDirectory(source);
			UserLog log = new UserLog("admin", "Move folder "
					+ source.getName() + " to " + dest.getPath(), date);
			iLog.log(log);
		}

		return true;
	}

	@Override
	public void deleteFile(File file) throws IOException {

		if (file.isDirectory()) {

			// directory is empty, then delete it
			if (file.list().length == 0) {

				file.delete();
			} else {

				// list all the directory contents
				String files[] = file.list();

				for (String temp : files) {

					File fileDelete = new File(file, temp);

					// recursive delete
					deleteFile(fileDelete);
				}

				// check the directory again, if empty then delete it
				if (file.list().length == 0) {
					file.delete();
					ILog iLog = new ILogImpl();
					Date date = new Date();

					UserLog log = new UserLog("admin", "Delete folder "
							+ file.getName(), date);
					iLog.log(log);
				}
			}

		} else {
			file.delete();
			ILog iLog = new ILogImpl();
			Date date = new Date();

			UserLog log = new UserLog("admin", "Delete file " + file.getName(),
					date);
			iLog.log(log);
		}

	}

	@Override
	public long calSizeOfFile(String path) {
		long sizeOfFile = 0;
		File file = new File(path);
		if (file.isFile())
			sizeOfFile = file.length();
		else
			sizeOfFile = FileUtils.sizeOfDirectory(file);

		return sizeOfFile;
	}
}
